/*
 * FlowLayout.java
 *
 * Created on 2004/05/03 +0900
 *
 * $Revision: 59 $
 * $Date: 2008-12-28 19:22:21 +0000 (Sun, 28 Dec 2008) $
 */

package org.gikolet.framework.ui;

/**
 * @author Tetsutaro (latest modification by $Author: tetsutaro.ss $)
 * @version $Revision: 59 $ $Date: 2008-12-28 19:22:21 +0000 (Sun, 28 Dec 2008) $
 */
public class FlowLayout implements Layout {
    public static final int LEFT = 0;
    public static final int CENTER = 1;
    public static final int RIGHT = 2;
    public static final int LEADING = 3;
    public static final int TRAILING = 4;

    private int newAlign;

    private int hgap;
    private int vgap;

    public FlowLayout() {
	this(CENTER, 5, 5);
    }

    public FlowLayout(int align) {
	this(align, 5, 5);
    }

    public FlowLayout(int align, int hgap, int vgap) {
	this.hgap = hgap;
	this.vgap = vgap;
	setAlignment(align);
    }

    public int getAlignment() {
	return this.newAlign;
    }

    private void setAlignment(int align) {
	this.newAlign = align;

	switch (align) {
	    case LEADING:
		break;
	    case TRAILING:
		break;
	    default:
		break;
	}
    }

    public int getHgap() {
	return this.hgap;
    }

    public int getVgap() {
	return this.vgap;
    }

    public Dimension getPreferredLayoutSize(Widget target, int hintWidth,
	    int hintHeight) {
	Dimension dim = new Dimension(0, 0);
	boolean firstVisibleComponent = true;

	for (int i = 0; i < target.getWidgetCount(); i++) {
	    Widget m = target.getWidget(i);
	    if (m.isVisible()) {
		Dimension d = m.getPreferredSize(Widget.DEFAULT_LAYOUT,
			Widget.DEFAULT_LAYOUT);

		dim.setSize(dim.getWidth(), Math.max(dim.getHeight(), d
			.getHeight()));

		if (firstVisibleComponent) {
		    firstVisibleComponent = false;

		} else {
		    dim.setSize(dim.getWidth() + this.hgap, dim.getHeight());
		}
		dim.setSize(dim.getWidth() + d.getWidth(), dim.getHeight());
	    }
	}
	dim.setSize(dim.getWidth() + target.getLeftInset()
		+ target.getRightInset() + this.hgap * 2, dim.getHeight()
		+ target.getTopInset() + target.getBottomInset() + this.vgap
		* 2);
	return dim;
    }

    private void moveComponents(Widget target, int x, int y, int width,
	    int height, int rowStart, int rowEnd, boolean ltr) {
	switch (this.newAlign) {
	    case LEFT:
		x += ltr ? 0 : width;
		break;
	    case CENTER:
		x += width / 2;
		break;
	    case RIGHT:
		x += ltr ? width : 0;
		break;
	    case LEADING:
		break;
	    case TRAILING:
		x += width;
		break;
	}
	for (int i = rowStart; i < rowEnd; i++) {
	    Widget m = target.getWidget(i);
	    Rectangle rb = m.getBounds();
	    if (m.isVisible()) {
		if (ltr) {
		    m.setLocation(x, y + (height - rb.getHeight()) / 2);
		} else {
		    m.setLocation(target.getSize().getWidth() - x
			    - rb.getWidth(), y + (height - rb.getHeight()) / 2);
		}
		x += rb.getWidth() + this.hgap;
	    }
	}
    }

    public void layout(Widget target) {
	int maxwidth = target.getSize().getWidth()
		- (target.getLeftInset() + target.getRightInset() + this.hgap * 2);
	int x = 0, y = target.getTopInset() + this.vgap;
	int rowh = 0, start = 0;

	boolean ltr = true;

	for (int i = 0; i < target.getWidgetCount(); i++) {
	    Widget m = target.getWidget(i);
	    if (m.isVisible()) {
		Dimension d = m.getPreferredSize(Widget.DEFAULT_LAYOUT,
			Widget.DEFAULT_LAYOUT);
		m.setSize(d.getWidth(), d.getHeight());

		if ((x == 0) || ((x + d.getWidth()) <= maxwidth)) {
		    if (x > 0) {
			x += this.hgap;
		    }
		    x += d.getWidth();
		    rowh = Math.max(rowh, d.getHeight());

		} else {
		    moveComponents(target, target.getLeftInset() + this.hgap,
			    y, maxwidth - x, rowh, start, i, ltr);
		    x = d.getWidth();
		    y += this.vgap + rowh;
		    rowh = d.getHeight();
		    start = i;
		}
	    }
	}
	moveComponents(target, target.getLeftInset() + this.hgap, y, maxwidth
		- x, rowh, start, target.getControlCount(), ltr);
    }
}
